package cn.com.self.apis.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @Description 日期转换工具类
 *
 * @date 2019-03-17
 */
public class DateFormatUtil {
    private static ConcurrentMap<String, SimpleDateFormat> regMap = new ConcurrentHashMap<String, SimpleDateFormat>();

    private static void initMap() {
        //Tue Oct 03 2017 00:00:00 GMT 0800 (??-????????????é?′)
        regMap.put("\\d{11}|\\d{13}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        regMap.put("^\\d{4}-\\d{1,2}-\\d{1,2}$", new SimpleDateFormat("yyyy-MM-dd"));
        regMap.put("^\\d{4}\\d{1,2}\\d{1,2}$", new SimpleDateFormat("yyyyMMdd"));
        regMap.put("^\\d{4}/\\d{1,2}/\\d{1,2}$", new SimpleDateFormat("yyyy/MM/dd"));
        regMap.put("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}$", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        regMap.put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{1,2}:\\d{1,2}$", new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"));
        regMap.put("^\\d{4}-\\d{1,2}-\\d{1,2}[a-zA-Z]\\d{1,2}:\\d{1,2}:\\d{1,2}\\.\\d{3}[a-zA-Z]$", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"));
        regMap.put("^[a-zA-Z]{3}\\s[a-zA-Z]{3}\\s\\d{2}\\s\\d{4}\\s\\d{2}:\\d{2}:\\d{2}\\s[A-Z]{3}\\s\\d{4}(\\s)*(\\(){0,1}[\\u4E00-\\u9FFF]*(\\)){0,1}$", new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss", Locale.ENGLISH));
        regMap.put("^[a-zA-Z]{3}\\s[a-zA-Z]{3}\\s\\d{2}\\s\\d{4}\\s\\d{2}:\\d{2}:\\d{2}\\s[A-Z]{3}\\s\\d{4}$", new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss", Locale.ENGLISH));
        regMap.put("^[a-zA-Z]{3}\\s[a-zA-Z]{3}\\s\\d{2}\\s\\d{2}:\\d{2}:\\d{2}\\s[A-Z]{3}\\s\\d{4}$", new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH));
//        regMap.put("(Mon|Tues|Wed|Thur|Fri|Sat|Sun)\\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept|Oct|Nov|Dec)\\s+\\d\\d\\s+\\d\\d:\\d\\d:\\d\\d\\s+CST\\s+\\d\\d\\d\\d", new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy",Locale.ENGLISH));
    }

    public static Date parseDate(String text) {
        initMap();
        for (Map.Entry<String, SimpleDateFormat> entry : regMap.entrySet()) {
            String key = entry.getKey();
            SimpleDateFormat format = entry.getValue();
            try {
                if (key.equals("^\\d{4}-\\d{1,2}-\\d{1,2}[a-zA-Z]\\d{1,2}:\\d{1,2}:\\d{1,2}\\.\\d{3}[a-zA-Z]$")) {
                    if (text.matches(key)) {
                        text = text.replace("Z", " UTC");
                        return format.parse(text);
                    }
                }
                if (key.equals("^[a-zA-Z]{3}\\s[a-zA-Z]{3}\\s\\d{2}\\s\\d{4}\\s\\d{2}:\\d{2}:\\d{2}\\s[A-Z]{3}\\s\\d{4}(\\s)*(\\(){0,1}[\\u4E00-\\u9FFF]*(\\)){0,1}$")) {
                    if (text.matches(key)) {
                        text = text.replace(" GMT 0800", "");
                        return format.parse(text);
                    }
                }
                // 处理feign调用13位时间戳
                if (key.equals("\\d{11}|\\d{13}")) {
                    if (text.matches(key)) {
                        return format.parse(stampToDate(text));
                    }
                }
                if (text.endsWith(")")) {
                    text = text.substring(0, text.indexOf("(")).trim();
                }
                if (text.matches(key)) {
                    System.out.println(key);
                    return format.parse(text);
                }
            } catch (ParseException e) {
                AssertUtil.throwException("无法将字符串[" + text + "]转换成日期格式！");
            }
        }
        return null;
    }

    /**
     * @Description 将时间戳转换为时间
     *
     * @date 2019-03-20
     * @param s
     * @return java.lang.String
     */
    public static String stampToDate(String s){
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt = new Long(s);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }

    /**
     * @Description
     * 获取当前日期所在月份内任意一天的下一个月的最后一天【当前：2017-08-23，return:2017-09-30】
     *
     * @date 2019-03-17
     * @param currentDate【currentDate 一定非空】
     * @return java.util.Date
     */
    public static Date getNextMonthLastDay(Date currentDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.MONTH, 2);
        calendar.set(Calendar.DATE, 1);
        calendar.add(Calendar.DATE, -1);

        return calendar.getTime();
    }

    /**
     * @Description 将Date类型日期按指定类型转换成字符串
     *
     * @date 2019-03-17
     * @param date 日期
     * @param formatPatten  格式表达式
     * @return java.lang.String 转换后的日期字符串
     */
    public static String formatDateToString(Date date, String formatPatten) {
        String dateStr = null;
        try {
            dateStr = new SimpleDateFormat(formatPatten).format(date);

        } catch (Exception e) {
            AssertUtil.throwException("日期转换异常！");
        }
        return dateStr;
    }

    /**
     * @Description
     *
     * @date 2019-03-17
     * @param text 日期字符串
     * @param formatPatten 转换日期格式
     * @return java.lang.String 将日期字符串转换为指定格式
     */
    public static String parseStringDate(String text, String formatPatten) {
        String dateString = null;
        Date date = parseDate(text);
        if (date != null) {
            dateString = formatDateToString(date, formatPatten);
        }
        return dateString;
    }

    public static Date formatDate(Date date, String formartPatten) {
        SimpleDateFormat format = new SimpleDateFormat(formartPatten);
        String dateStr = formatDateToString(date, formartPatten);
        try {
            return format.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
            AssertUtil.throwException("日期格式转换异常");
        }
        return null;
    }

    /**
     * @Description 获取某一日期的月份
     *
     * @date 2019-03-17
     * @param date
     * @return int
     */
    public static int getMonthOfDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH);
    }

    public static int getYearOfDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    public static List<Date> getWeekDayOfYear(int year) {
        Calendar calendar = new GregorianCalendar(year, 0, 1);
        int i = 1;
        List<Date> list = new ArrayList<Date>();
        while (calendar.get(Calendar.YEAR) < year + 1) {
            calendar.set(Calendar.WEEK_OF_YEAR, i++);
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
            list.add(calendar.getTime());
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
            list.add(calendar.getTime());
        }
        return list;
    }

    /**
     * @Description 比较当前日期是否在指定日期区间之间(精确到天)
     *
     * @date 2019-03-17
     * @param checkDate 被比较的日期
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return boolean 比较结果
     */
    public static boolean checkDateBetween(Date checkDate, Date startDate, Date endDate) {
        String formatPatten = "yyyy-MM-dd";
        String check = DateFormatUtil.formatDateToString(checkDate, formatPatten);
        String start = DateFormatUtil.formatDateToString(startDate, formatPatten);
        String end = DateFormatUtil.formatDateToString(endDate, formatPatten);
        int c1 = check.compareTo(start);
        int c2 = check.compareTo(end);
        return c1 >= 0 && c2 <= 0;
    }

    public static boolean checkDateLT(Date srcDate,Date tarDate){
        String formart = "yyyyMMdd";
        String src = formatDateToString(srcDate, formart);
        String tar = formatDateToString(tarDate, formart);
        return src.compareTo(tar)<0;
    }
}
